home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Media 23
/
PC MEDIA CD23.iso
/
share
/
prog
/
newmat
/
myexcept.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-17
|
9KB
|
320 lines
//$$except.cpp Exception handler
// Copyright (C) 1993,4: R B Davies
#define WANT_STREAM // include.h will get stream fns
#include "include.h" // include standard files
#include "boolean.h"
#include "myexcept.h" // for exception handling
//#define REG_DEREG // for print out uses of new/delete
//#define CLEAN_LIST // to print entries being added to
// or deleted from cleanup list
#ifdef SimulateExceptions
void Throw()
{
for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
jan->CleanUp();
JumpBase::jl = JumpBase::jl->ji;
if ( ! JumpBase::jl ) Terminate();
Exception::last = JumpBase::jl->trace;
longjmp(JumpBase::jl->env, 1);
}
void Throw(const Exception& exc) { JumpBase::type = exc.type(); Throw(); }
#endif // end of simulate exceptions
void Exception::PrintTrace(Boolean)
{
cout << "\n";
{
for (Tracer* et = last; et; et=et->previous)
cout << " * " << et->entry << "\n";
}
}
Exception::Exception(int action)
{
if (action)
{
cout << "\nAn exception has occurred: call trace follows.";
PrintTrace();
if (action < 0) exit(1);
}
}
#ifdef SimulateExceptions
Janitor::Janitor()
{
if (do_not_link)
// if (do_not_link || !JumpBase::jl) // second term is for global
// declarations when the JumpItem
// list might be empty
{
do_not_link = FALSE; NextJanitor = 0; OnStack = FALSE;
#ifdef CLEAN_LIST
cout << "Not added to clean-list " << (unsigned long)this << "\n";
#endif
}
else
{
OnStack = TRUE;
#ifdef CLEAN_LIST
cout << "Add to clean-list " << (unsigned long)this << "\n";
#endif
NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
}
}
Janitor::~Janitor()
{
// expect the item to be deleted to be first on list
// but must be prepared to search list
if (OnStack)
{
#ifdef CLEAN_LIST
cout << "Delete from clean-list " << (unsigned long)this << "\n";
#endif
Janitor* lastjan = JumpBase::jl->janitor;
if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
else
{
for (Janitor* jan = lastjan->NextJanitor; jan;
jan = lastjan->NextJanitor)
{
if (jan==this)
{ lastjan->NextJanitor = jan->NextJanitor; return; }
lastjan=jan;
}
cout << "\nCannot resolve memory linked list\n";
cout << "See notes in except.cpp for details\n";
Throw(Exception(-1));
/*
This message occurs when a call to ~Janitor() occurs, apparently without
a corresponding call to Janitor(). This could happen if my way of
deciding whether a constructor is being called by new fails. It can also
happen if you have a class derived from Janitor which does not include a
copy constructor [ eg X(const &X) ]. Possibly also if delete is applied
an object on the stack (ie not called by new). Otherwise, it is a bug in
Newmat or your compiler. If you don't #define TEMPS_DESTROYED_QUICKLY
you will get this error with Microsoft C 7.0. There are probably
situations where you will get this when you do define
TEMPS_DESTROYED_QUICKLY. This is a bug in MSC. Beware of "operator"
statements for defining conversions; particularly for converting from a
Base class to a Derived class.
You may get away with simply deleting this error message and Throw statement
if you can't find a better way of overcoming the problem. In any case please
tell me if you get this error message, particularly for compilers apart from
Microsoft C.
*/
}
}
}
JumpItem* JumpBase::jl; // will be set to zero
long JumpBase::type;
jmp_buf JumpBase::env;
Boolean Janitor::do_not_link; // will be set to FALSE
// static JumpItem JI; // need JumpItem at head of list
int JanitorInitializer::ref_count;
JanitorInitializer::JanitorInitializer()
{
if (ref_count++ == 0)
{
new JumpItem; // need JumpItem at head of list
}
}
#endif // end of SimulateExceptions
Tracer* Exception::last; // will be set to zero
void Terminate()
{
cout << "\nThere has been an exception with no handler - exiting\n";
exit(1);
}
#ifdef DO_FREE_CHECK
// Routines for tracing whether new and delete calls are balanced
FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
{ FreeCheck::next = this; }
FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
FCLRealArray::FCLRealArray(void* t, char* o, int s)
: Operation(o), size(s) { ClassStore=t; }
FCLIntArray::FCLIntArray(void* t, char* o, int s)
: Operation(o), size(s) { ClassStore=t; }
FreeCheckLink* FreeCheck::next;
int FreeCheck::BadDelete;
void FCLClass::Report()
{ cout << " " << ClassName << " " << (unsigned long)ClassStore << "\n"; }
void FCLRealArray::Report()
{
cout << " " << Operation << " " << (unsigned long)ClassStore <<
" " << size << "\n";
}
void FCLIntArray::Report()
{
cout << " " << Operation << " " << (unsigned long)ClassStore <<
" " << size << "\n";
}
void FreeCheck::Register(void* t, char* name)
{
FCLClass* f = new FCLClass(t,name);
if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
#ifdef REG_DEREG
cout << "Registering " << name << " " << (unsigned long)t << "\n";
#endif
}
void FreeCheck::RegisterR(void* t, char* o, int s)
{
FCLRealArray* f = new FCLRealArray(t,o,s);
if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
#ifdef REG_DEREG
cout << o << " " << s << " " << (unsigned long)t << "\n";
#endif
}
void FreeCheck::RegisterI(void* t, char* o, int s)
{
FCLIntArray* f = new FCLIntArray(t,o,s);
if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
#ifdef REG_DEREG
cout << o << " " << s << " " << (unsigned long)t << "\n";
#endif
}
void FreeCheck::DeRegister(void* t, char* name)
{
FreeCheckLink* last = 0;
#ifdef REG_DEREG
cout << "Deregistering " << name << " " << (unsigned long)t << "\n";
#endif
for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
{
if (fcl->ClassStore==t)
{
if (last) last->next = fcl->next; else next = fcl->next;
delete fcl; return;
}
last = fcl;
}
cout << "\nRequest to delete non-existent object of class and location:\n";
cout << " " << name << " " << (unsigned long)t << "\n";
BadDelete++;
Exception::PrintTrace(TRUE);
cout << "\n";
}
void FreeCheck::DeRegisterR(void* t, char* o, int s)
{
FreeCheckLink* last = 0;
#ifdef REG_DEREG
cout << o << " " << s << " " << (unsigned long)t << "\n";
#endif
for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
{
if (fcl->ClassStore==t)
{
if (last) last->next = fcl->next; else next = fcl->next;
if (((FCLRealArray*)fcl)->size != s)
{
cout << "\nArray sizes don't agree:\n";
cout << " " << o << " " << (unsigned long)t
<< " " << s << "\n";
Exception::PrintTrace(TRUE);
cout << "\n";
}
delete fcl; return;
}
last = fcl;
}
cout << "\nRequest to delete non-existent real array:\n";
cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
BadDelete++;
Exception::PrintTrace(TRUE);
cout << "\n";
}
void FreeCheck::DeRegisterI(void* t, char* o, int s)
{
FreeCheckLink* last = 0;
#ifdef REG_DEREG
cout << o << " " << s << " " << (unsigned long)t << "\n";
#endif
for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
{
if (fcl->ClassStore==t)
{
if (last) last->next = fcl->next; else next = fcl->next;
if (((FCLIntArray*)fcl)->size != s)
{
cout << "\nArray sizes don't agree:\n";
cout << " " << o << " " << (unsigned long)t
<< " " << s << "\n";
Exception::PrintTrace(TRUE);
cout << "\n";
}
delete fcl; return;
}
last = fcl;
}
cout << "\nRequest to delete non-existent int array:\n";
cout << " " << o << " " << (unsigned long)t << " " << s << "\n";
BadDelete++;
Exception::PrintTrace(TRUE);
cout << "\n";
}
void FreeCheck::Status()
{
if (next)
{
cout << "\nObjects of the following classes remain undeleted:\n";
for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
cout << "\n";
}
else cout << "\nNo objects remain undeleted\n\n";
if (BadDelete)
{
cout << "\nThere were " << BadDelete <<
" requests to delete non-existent items\n\n";
}
}
#endif